iT邦幫忙

3

Java數字計算:使用BigInteger與BigDecimal

  • 分享至 

  • xImage
  •  

因為Java(大部分程式語言都是)是使用IEEE754演算標準,小數計算會有誤差,所以需要精確的做四則運算,需用更適用的類別來處理。

BigInteger

在Java中整數的最大值為9223372036854775807,最小值是-9223372036854775808,如果要表示超過這個範圍的數字,就要使用BigInteger類別。

因為數字已經大於int及long的範圍了,所以傳入BigInteger中時會使用String

BigInteger n = new BigInteger("9223372036854775808");

四則運算則要用add、subtract、multiply、divide等(有BigInteger.ONE、BigInteger.TEN等保留字)

BigInteger n1 = new BigInteger("9223372036854775808");
BigInteger n2 = new BigInteger("9223372036854775809");
n.add(n2);
n.subtract(n2);
n.multiply(n2);
n.divide(n2);

兩數比較則可以用equals()與compareTo()

BigInteger n1 = new BigInteger("200");
BigInteger n2 = new BigInteger("100");
n1.compareTo(n2);
//相等回傳0,n1>n2回傳1,n1<n2回傳-1
n1.equals(n2);
//等於回傳true,否則回傳false

BigInteger與基本型態之間的轉換

n1.longValue(); //轉為long
n1.intValue();  //轉為int
BigInteger.valueOf(100); //由int轉為BigInteger

如果由BigInteger轉回基本型態的數字超過基本型態可以容納的範圍,會使數字失去精度,此時就可以使用intValueExtract()、longValueExtract()等,使之拋出例外。

BigInteger n1 = new BigInteger("3333333333333333333333333");
n1.intValueExact();
//會拋出 java.lang.ArithmeticException例外

一般於Math類別常用的方法BigInteger也皆有支援(sqrt除外)

BigInteger n1 = new BigInteger("200");
BigInteger n2 = new BigInteger("100");
n1.pow(2);
n1.abs();
n1.min(n2);
n1.max(n2);

BigDecimal

與BigInteger方法大同小異,可以防止小數計算時因IEEE754規範所造成的誤差。
比較特別的是四捨五入、無條件捨去、無條件進入的處理
先提一下Math類別的處理:

Math.round(5.4);    //四捨五入
Math.ceil(5.4);     //無條件進位
Math.floor(5.4);    //無條件捨去

要注意,無條件進位是往數字大的方向進位,無條件捨去是往數字小的方向捨去
而此種進位方式如果牽扯到小數,有可能會因為IEEE754標準而發生誤差。
舉例:-5.5用Math.round()四捨五入的結果會是-5
此時就可以使用BigDecimal的進位方式:

BigDecimal r = new BigDecimal(-3.3456789); 
BigDecimal i1 = r.setScale(3,RoundingMode.UP);
BigDecimal i2 = r.setScale(3,RoundingMode.DOWN);
BigDecimal i3 = r.setScale(3,RoundingMode.CEILING);
BigDecimal i4 = r.setScale(3,RoundingMode.FLOOR);
BigDecimal i5 = r.setScale(3,RoundingMode.HALF_UP);
BigDecimal i6 = r.setScale(3,RoundingMode.HALF_DOWN);
BigDecimal i7 = r.setScale(3,RoundingMode.HALF_EVEN);
  1. UP:往該數絕對值大的方向進位
  2. DOWN:往該數絕對值小的方向捨去
  3. CEILING:與Math.ceil的進位方式相同
  4. FLOOR:與Math.floor的進位方式相同
  5. HALF_UP:四捨五入(不會有誤差)
  6. HALF_DOWN:五捨去,六以上進位
  7. HALF_EVEN:銀行家捨入法

而BigDecimal可以用setScale來設定量級
r.setScale(3,RoundingMode.HALF_UP):這就代表四捨五入到小數點後第三位

比較一下其餘可能影響進位的類別

  1. DecimalFormat(還是會有IEEE754所造成的精準度問題):比較常用在格式化數字
DecimalFormat df = new DecimalFormat("#.00");
System.out.println(df.format(-3.155));
  1. String.format:會無條件捨去
double d = -3.146;
String result = String.format("%.2f",d);
System.out.println(result);

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言